home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-19 / iritsm3s.zip / CAGD_AUX.C < prev    next >
C/C++ Source or Header  |  1992-01-02  |  24KB  |  751 lines

  1. /******************************************************************************
  2. * Cagd_aux.c - auxiliary routine to interface to different free from types.   *
  3. *******************************************************************************
  4. * Written by Gershon Elber, July. 90.                          *
  5. ******************************************************************************/
  6.  
  7. #include "cagd_loc.h"
  8.  
  9. /******************************************************************************
  10. * Given a crv and parameter value t, evaluate the curve at t.              *
  11. ******************************************************************************/
  12. CagdRType *CagdCrvEval(CagdCrvStruct *Crv, CagdRType t)
  13. {
  14.     switch (Crv -> GType) {
  15.     case CAGD_CBEZIER_TYPE:
  16.         return BzrCrvEvalAtParam(Crv, t);
  17.     case CAGD_CBSPLINE_TYPE:
  18.         return BspCrvEvalAtParam(Crv, t);
  19.     case CAGD_CPOWER_TYPE:
  20.         FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
  21.         return NULL;
  22.     default:
  23.         FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
  24.         return NULL;
  25.     }
  26. }
  27.  
  28. /******************************************************************************
  29. * Given a srf and parameter values u,v, evaluate the surface at u,v.          *
  30. ******************************************************************************/
  31. CagdRType *CagdSrfEval(CagdSrfStruct *Srf, CagdRType u, CagdRType v)
  32. {
  33.     switch (Srf -> GType) {
  34.     case CAGD_SBEZIER_TYPE:
  35.         return BzrSrfEvalAtParam(Srf, u, v);
  36.     case CAGD_SBSPLINE_TYPE:
  37.         return BspSrfEvalAtParam(Srf, u, v);
  38.     case CAGD_SPOWER_TYPE:
  39.         FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
  40.         return NULL;
  41.     default:
  42.         FATAL_ERROR(CAGD_ERR_UNDEF_SRF);
  43.         return NULL;
  44.     }
  45. }
  46.  
  47. /******************************************************************************
  48. * Given a curve - subdivide it into two at the given parametric value.        *
  49. * Returns pointer to first curve in a list of two curves (subdivided ones).   *
  50. ******************************************************************************/
  51. CagdCrvStruct *CagdCrvSubdivAtParam(CagdCrvStruct *Crv, CagdRType t)
  52. {
  53.     switch (Crv -> GType) {
  54.     case CAGD_CBEZIER_TYPE:
  55.         return BzrCrvSubdivAtParam(Crv, t);
  56.     case CAGD_CBSPLINE_TYPE:
  57.         return BspCrvSubdivAtParam(Crv, t);
  58.     case CAGD_CPOWER_TYPE:
  59.         FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
  60.         return NULL;
  61.     default:
  62.         FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
  63.         return NULL;
  64.     }
  65. }
  66.  
  67. /******************************************************************************
  68. * Given a curve - returns a sub region within the specified domain.           *
  69. ******************************************************************************/
  70. CagdCrvStruct *CagdCrvRegionFromCrv(CagdCrvStruct *Crv, CagdRType t1,
  71.                             CagdRType t2)
  72. {
  73.     CagdRType TMin, TMax;
  74.     CagdCrvStruct *Crvs;
  75.     CagdBType
  76.     NewCrv = FALSE;
  77.  
  78.     switch (Crv -> GType) {
  79.     case CAGD_CBEZIER_TYPE:
  80.         TMin = 0.0;
  81.         TMax = 1.0;
  82.         break;
  83.     case CAGD_CBSPLINE_TYPE:
  84.             BspCrvDomain(Crv, &TMin, &TMax);
  85.         break;
  86.     case CAGD_CPOWER_TYPE:
  87.         FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
  88.         return NULL;
  89.     default:
  90.         FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
  91.         return NULL;
  92.     }
  93.  
  94.     if (t1 > t2) SWAP(CagdRType, t1, t2);
  95.  
  96.     if (!APX_EQ(t1, TMin)) {
  97.         Crvs = CagdCrvSubdivAtParam(Crv, t1);
  98.     Crv = Crvs -> Pnext;
  99.     Crvs -> Pnext = NULL;
  100.     CagdCrvFree(Crvs);               /* Free the first region. */
  101.     NewCrv = TRUE;
  102.     }
  103.  
  104.     if (APX_EQ(t2, TMax))
  105.     return NewCrv ? Crv : CagdCrvCopy(Crv);
  106.     else {
  107.     Crvs = CagdCrvSubdivAtParam(Crv, t2);
  108.  
  109.     if (NewCrv) CagdCrvFree(Crv);
  110.  
  111.         CagdCrvFree(Crvs -> Pnext);          /* Free the second region. */
  112.         Crvs -> Pnext = NULL;
  113.         return Crvs;                /* Returns the first region. */
  114.     }
  115. }
  116.  
  117. /******************************************************************************
  118. * Given a curve - refine it at the given n knots as defined by vector t.      *
  119. * If Replace is TRUE, the values replaces current vector instead.          *
  120. * Returns pointer to refined crv (Note Bezier will be converted into spline). *
  121. ******************************************************************************/
  122. CagdCrvStruct *CagdCrvRefineAtParams(CagdCrvStruct *Crv, CagdBType Replace,
  123.                              CagdRType *t, int n)
  124. {
  125.     CagdCrvStruct *BspCrv, *TCrv;
  126.  
  127.     switch (Crv -> GType) {
  128.     case CAGD_CBEZIER_TYPE:
  129.             BspCrv = CnvrtBezier2BsplineCrv(Crv);
  130.         TCrv = BspCrvKnotInsertNDiff(BspCrv, Replace, t, n);
  131.         CagdCrvFree(BspCrv);
  132.         return TCrv;
  133.     case CAGD_CBSPLINE_TYPE:
  134.         return BspCrvKnotInsertNDiff(Crv, Replace, t, n);
  135.     case CAGD_CPOWER_TYPE:
  136.         FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
  137.         return NULL;
  138.     default:
  139.         FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
  140.         return NULL;
  141.     }
  142. }
  143.  
  144. /******************************************************************************
  145. * Return a new curve reversed by reversing the ctl polygon.                   *
  146. ******************************************************************************/
  147. CagdCrvStruct *CagdCrvReverse(CagdCrvStruct *Crv)
  148. {
  149.     CagdBType
  150.     IsNotRational = !CAGD_IS_RATIONAL_CRV(Crv);
  151.     int i, Len, Col,
  152.     Length = Crv -> Length,
  153.     MaxCoord = CAGD_NUM_OF_PT_COORD(Crv -> PType);
  154.     CagdCrvStruct
  155.         *ReversedCrv = CagdCrvCopy(Crv);
  156.     CagdRType *KV,
  157.     **Points = ReversedCrv -> Points;
  158.  
  159.     switch (Crv -> GType) {
  160.     case CAGD_CBEZIER_TYPE:
  161.     case CAGD_CBSPLINE_TYPE:
  162.         break;
  163.     case CAGD_CPOWER_TYPE:
  164.         FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
  165.         return NULL;
  166.     default:
  167.         FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
  168.         return NULL;
  169.     }
  170.  
  171.     /* Reverse the Ctl Polygon: */
  172.     Len = Length / 2;
  173.     for (Col = 0; Col < Len; Col++)
  174.     for (i = IsNotRational; i <= MaxCoord; i++)
  175.         SWAP(CagdRType,
  176.          Points[i][Col],
  177.          Points[i][Length - Col - 1]);
  178.  
  179.     /* Reverse the knot vector if it exists: */
  180.     if (Crv -> GType == CAGD_CBSPLINE_TYPE &&
  181.     Crv -> KnotVector != NULL) {
  182.     KV = BspKnotReverse(Crv -> KnotVector, Crv -> Order + Length);
  183.     CagdFree((VoidPtr) ReversedCrv -> KnotVector);
  184.     ReversedCrv -> KnotVector = KV;
  185.     }
  186.  
  187.     return ReversedCrv;
  188. }
  189.  
  190. /******************************************************************************
  191. * Return a new curve representing the same curve but with degree raised.      *
  192. ******************************************************************************/
  193. CagdCrvStruct *CagdCrvDegreeRaise(CagdCrvStruct *Crv)
  194. {
  195.     switch (Crv -> GType) {
  196.     case CAGD_CBEZIER_TYPE:
  197.         return BzrCrvDegreeRaise(Crv);
  198.     case CAGD_CBSPLINE_TYPE:
  199.         return BspCrvDegreeRaise(Crv);
  200.     case CAGD_CPOWER_TYPE:
  201.         FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
  202.         return NULL;
  203.     default:
  204.         FATAL_ERROR(CAGD_ERR_UNDEF_SRF);
  205.         return NULL;
  206.     }
  207. }
  208.  
  209. /******************************************************************************
  210. * Return a new surface representing the same surface but with degree raised.  *
  211. ******************************************************************************/
  212. CagdSrfStruct *CagdSrfDegreeRaise(CagdSrfStruct *Srf, CagdSrfDirType Dir)
  213. {
  214.     switch (Srf -> GType) {
  215.     case CAGD_SBEZIER_TYPE:
  216.         return BzrSrfDegreeRaise(Srf, Dir);
  217.     case CAGD_SBSPLINE_TYPE:
  218.         return BspSrfDegreeRaise(Srf, Dir);
  219.     case CAGD_SPOWER_TYPE:
  220.         FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
  221.         return NULL;
  222.     default:
  223.         FATAL_ERROR(CAGD_ERR_UNDEF_SRF);
  224.         return NULL;
  225.     }
  226. }
  227.  
  228. /******************************************************************************
  229. * Extracts an iso curve from the surface as spcified by Dir and t.          *
  230. ******************************************************************************/
  231. CagdCrvStruct *CagdCrvFromSrf(CagdSrfStruct *Srf, CagdRType t,
  232.                             CagdSrfDirType Dir)
  233. {
  234.     switch (Srf -> GType) {
  235.     case CAGD_SBEZIER_TYPE:
  236.         return BzrSrfCrvFromSrf(Srf, t, Dir);
  237.     case CAGD_SBSPLINE_TYPE:
  238.         return BspSrfCrvFromSrf(Srf, t, Dir);
  239.     case CAGD_SPOWER_TYPE:
  240.         FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
  241.         return NULL;
  242.     default:
  243.         FATAL_ERROR(CAGD_ERR_UNDEF_SRF);
  244.         return NULL;
  245.     }
  246. }
  247.  
  248. /******************************************************************************
  249. * Extracts a curve from the surface as spcified by Dir and Index.          *
  250. *   The curve is constructed as a single ROW/COL of the original surface.     *
  251. *   Note this curve may be not on the surface!                      *
  252. ******************************************************************************/
  253. CagdCrvStruct *CagdCrvFromMesh(CagdSrfStruct *Srf, int Index,
  254.                             CagdSrfDirType Dir)
  255. {
  256.     switch (Srf -> GType) {
  257.     case CAGD_SBEZIER_TYPE:
  258.         return BzrSrfCrvFromMesh(Srf, Index, Dir);
  259.     case CAGD_SBSPLINE_TYPE:
  260.         return BspSrfCrvFromMesh(Srf, Index, Dir);
  261.     case CAGD_SPOWER_TYPE:
  262.         FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
  263.         return NULL;
  264.     default:
  265.         FATAL_ERROR(CAGD_ERR_UNDEF_SRF);
  266.         return NULL;
  267.     }
  268. }
  269.  
  270. /******************************************************************************
  271. * Substitue a row/col from the given curve into the surface as spcified by    *
  272. * Dir and Index. Curve must have same PtType/Length and the surface row/col.  *
  273. ******************************************************************************/
  274. void CagdCrvToMesh(CagdCrvStruct *Crv, int Index,
  275.                     CagdSrfDirType Dir, CagdSrfStruct *Srf)
  276. {
  277.     CagdBType
  278.     IsNotRational = !CAGD_IS_RATIONAL_SRF(Srf);
  279.     int i, j,
  280.     Length = Crv -> Length,
  281.     ULength = Srf -> ULength,
  282.     VLength = Srf -> VLength,
  283.     MaxCoord = CAGD_NUM_OF_PT_COORD(Srf -> PType);
  284.     CagdRType *CrvP, *SrfP;
  285.  
  286.     if (Crv -> PType != Srf -> PType ||
  287.     Length != (Dir == CAGD_CONST_U_DIR ? VLength : ULength))
  288.     FATAL_ERROR(CAGD_ERR_PT_OR_LEN_MISMATCH);
  289.  
  290.     switch (Dir) {
  291.     case CAGD_CONST_U_DIR:
  292.         if (Index + 1 > ULength)
  293.         FATAL_ERROR(CAGD_ERR_INDEX_NOT_IN_MESH);
  294.  
  295.         for (i = IsNotRational; i <= MaxCoord; i++) {
  296.         CrvP = Crv -> Points[i];
  297.         SrfP = Srf -> Points[i] + Index * CAGD_NEXT_U(Srf);
  298.         for (j = 0; j < Length; j++) {
  299.             *SrfP = *CrvP++;
  300.             SrfP += CAGD_NEXT_V(Srf);
  301.         }
  302.         }
  303.         break;
  304.     case CAGD_CONST_V_DIR:
  305.         if (Index + 1 > VLength)
  306.         FATAL_ERROR(CAGD_ERR_INDEX_NOT_IN_MESH);
  307.  
  308.         for (i = IsNotRational; i <= MaxCoord; i++) {
  309.         CrvP = Crv -> Points[i];
  310.         SrfP = Srf -> Points[i] + Index * CAGD_NEXT_V(Srf);;
  311.         for (j = 0; j < Length; j++) {
  312.             *SrfP = *CrvP++;
  313.             SrfP += CAGD_NEXT_U(Srf);
  314.         }
  315.         }
  316.         break;
  317.     default:
  318.         FATAL_ERROR(CAGD_ERR_DIR_NOT_CONST_UV);
  319.         break;
  320.     }
  321. }
  322.  
  323. /******************************************************************************
  324. * Given a srf - subdivide it into two at given parametric value in given dir. *
  325. * Returns pointer to first srf in a list of two srfs (subdivided ones).       *
  326. ******************************************************************************/
  327. CagdSrfStruct *CagdSrfSubdivAtParam(CagdSrfStruct *Srf, CagdRType t,
  328.                                 CagdSrfDirType Dir)
  329. {
  330.     switch (Srf -> GType) {
  331.     case CAGD_SBEZIER_TYPE:
  332.         return BzrSrfSubdivAtParam(Srf, t, Dir);
  333.     case CAGD_SBSPLINE_TYPE:
  334.         return BspSrfSubdivAtParam(Srf, t, Dir);
  335.     case CAGD_SPOWER_TYPE:
  336.         FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
  337.         return NULL;
  338.     default:
  339.         FATAL_ERROR(CAGD_ERR_UNDEF_SRF);
  340.         return NULL;
  341.     }
  342. }
  343.  
  344. /******************************************************************************
  345. * Given a surface - returns a sub region within the specified domain, dir.    *
  346. ******************************************************************************/
  347. CagdSrfStruct *CagdSrfRegionFromSrf(CagdSrfStruct *Srf, CagdRType t1,
  348.                           CagdRType t2, CagdSrfDirType Dir)
  349. {
  350.     CagdRType TMin, TMax, R1, R2;
  351.     CagdSrfStruct *Srfs;
  352.     CagdBType
  353.     NewSrf = FALSE;
  354.  
  355.     switch (Srf -> GType) {
  356.     case CAGD_SBEZIER_TYPE:
  357.         TMin = 0.0;
  358.         TMax = 1.0;
  359.         break;
  360.     case CAGD_SBSPLINE_TYPE:
  361.             if (Dir == CAGD_CONST_U_DIR)
  362.         BspSrfDomain(Srf, &TMin, &TMax, &R1, &R2);
  363.         else
  364.         BspSrfDomain(Srf, &R1, &R2, &TMin, &TMax);
  365.         break;
  366.     case CAGD_SPOWER_TYPE:
  367.         FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
  368.         return NULL;
  369.     default:
  370.         FATAL_ERROR(CAGD_ERR_UNDEF_SRF);
  371.         return NULL;
  372.     }
  373.  
  374.     if (t1 > t2) SWAP(CagdRType, t1, t2);
  375.  
  376.     if (!APX_EQ(t1, TMin)) {
  377.     Srfs = CagdSrfSubdivAtParam(Srf, t1, Dir);
  378.     Srf = Srfs -> Pnext;
  379.     Srfs -> Pnext = NULL;
  380.     CagdSrfFree(Srfs);               /* Free the first region. */
  381.     NewSrf = TRUE;
  382.     }
  383.  
  384.     if (APX_EQ(t2, TMax))
  385.     return NewSrf ? Srf : CagdSrfCopy(Srf);
  386.     else {
  387.     Srfs = CagdSrfSubdivAtParam(Srf, t2, Dir);
  388.  
  389.     if (NewSrf) CagdSrfFree(Srf);
  390.  
  391.         CagdSrfFree(Srfs -> Pnext);          /* Free the second region. */
  392.         Srfs -> Pnext = NULL;
  393.     return Srfs;                /* Returns the first region. */
  394.     }
  395. }
  396.  
  397. /******************************************************************************
  398. * Given a surface - refine it at the given n knots as defined by vector t.    *
  399. * If Replace is TRUE, the values replaces current vector instead.          *
  400. * Returns pointer to refined srf (Note Bezier will be converted into spline). *
  401. ******************************************************************************/
  402. CagdSrfStruct *CagdSrfRefineAtParams(CagdSrfStruct *Srf, CagdSrfDirType Dir,
  403.                     CagdBType Replace, CagdRType *t, int n)
  404. {
  405.     CagdSrfStruct *BspSrf, *TSrf;
  406.  
  407.     switch (Srf -> GType) {
  408.     case CAGD_SBEZIER_TYPE:
  409.             BspSrf = CnvrtBezier2BsplineSrf(Srf);
  410.         TSrf = BspSrfKnotInsertNDiff(BspSrf, Dir, Replace, t, n);
  411.         CagdSrfFree(BspSrf);
  412.         return TSrf;
  413.     case CAGD_SBSPLINE_TYPE:
  414.         return BspSrfKnotInsertNDiff(Srf, Dir, Replace, t, n);
  415.     case CAGD_SPOWER_TYPE:
  416.         FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
  417.         return NULL;
  418.     default:
  419.         FATAL_ERROR(CAGD_ERR_UNDEF_SRF);
  420.         return NULL;
  421.     }
  422. }
  423.  
  424. /******************************************************************************
  425. * Given a curve and a parameter value t, returns the tangent direction at t.  *
  426. ******************************************************************************/
  427. CagdVecStruct *CagdCrvTangent(CagdCrvStruct *Crv, CagdRType t)
  428. {
  429.     switch (Crv -> GType) {
  430.     case CAGD_CBEZIER_TYPE:
  431.         return BzrCrvTangent(Crv, t);
  432.     case CAGD_CBSPLINE_TYPE:
  433.         return BspCrvTangent(Crv, t);
  434.     case CAGD_CPOWER_TYPE:
  435.         FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
  436.         return NULL;
  437.     default:
  438.         FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
  439.         return NULL;
  440.     }
  441. }
  442.  
  443. /******************************************************************************
  444. * Given a curve and a parameter value t, returns the binormal direction at t. *
  445. ******************************************************************************/
  446. CagdVecStruct *CagdCrvBiNormal(CagdCrvStruct *Crv, CagdRType t)
  447. {
  448.     switch (Crv -> GType) {
  449.     case CAGD_CBEZIER_TYPE:
  450.         return BzrCrvBiNormal(Crv, t);
  451.     case CAGD_CBSPLINE_TYPE:
  452.         return BspCrvBiNormal(Crv, t);
  453.     case CAGD_CPOWER_TYPE:
  454.         FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
  455.         return NULL;
  456.     default:
  457.         FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
  458.         return NULL;
  459.     }
  460. }
  461.  
  462. /******************************************************************************
  463. * Given a curve and a parameter value t, returns the normal direction at t.   *
  464. ******************************************************************************/
  465. CagdVecStruct *CagdCrvNormal(CagdCrvStruct *Crv, CagdRType t)
  466. {
  467.     switch (Crv -> GType) {
  468.     case CAGD_CBEZIER_TYPE:
  469.         return BzrCrvNormal(Crv, t);
  470.     case CAGD_CBSPLINE_TYPE:
  471.         return BspCrvNormal(Crv, t);
  472.     case CAGD_CPOWER_TYPE:
  473.         FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
  474.         return NULL;
  475.     default:
  476.         FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
  477.         return NULL;
  478.     }
  479. }
  480.  
  481. /******************************************************************************
  482. * Given a curve and an offset amount Offset, returns an approximation to the  *
  483. * offset curve by offseting the control polygon in the normal direction.      *
  484. ******************************************************************************/
  485. CagdCrvStruct *CagdCrvOffset(CagdCrvStruct *Crv, CagdRType OffsetDist)
  486. {
  487.     CagdBType
  488.     IsNotRational = !CAGD_IS_RATIONAL_CRV(Crv);
  489.     int i, j,
  490.     MaxCoord = CAGD_NUM_OF_PT_COORD(Crv -> PType),
  491.     Order = Crv -> Order,
  492.     Length = Crv -> Length;
  493.     CagdBType
  494.     HasNewKV = FALSE;
  495.     CagdVecStruct *N;
  496.     CagdCrvStruct
  497.     *OffsetCrv = CagdCrvCopy(Crv);
  498.     CagdRType *Nodes, *NodePtr,
  499.     **Points = OffsetCrv -> Points,
  500.     *KV = NULL;
  501.  
  502.     switch (Crv -> GType) {
  503.     case CAGD_CBEZIER_TYPE:
  504.         HasNewKV = TRUE;
  505.         KV = BspKnotUniformOpen(Length, Order, NULL);
  506.         break;
  507.     case CAGD_CBSPLINE_TYPE:
  508.         KV = Crv -> KnotVector;
  509.         break;
  510.     case CAGD_CPOWER_TYPE:
  511.         FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
  512.         return NULL;
  513.     default:
  514.         FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
  515.         return NULL;
  516.     }
  517.  
  518.     Nodes = BspKnotNodes(KV, Length + Order, Order);
  519.     NodePtr = Nodes;
  520.  
  521.     if (IsNotRational)
  522.     for (j = 0; j < Length; j++) {
  523.         N = CagdCrvNormal(Crv, *NodePtr++);
  524.         for (i = 1; i <= MaxCoord; i++)
  525.         Points[i][j] += N -> Vec[i - 1] * OffsetDist;
  526.     }
  527.     else
  528.     for (j = 0; j < Length; j++) {
  529.         N = CagdCrvNormal(Crv, *NodePtr++);
  530.         for (i = 1; i <= MaxCoord; i++)
  531.         Points[i][j] = Points[i][j] +
  532.                    N -> Vec[i - 1] * OffsetDist * Points[W][j];
  533.     }
  534.  
  535.     if (HasNewKV)
  536.     CagdFree((VoidPtr) KV);
  537.     CagdFree((VoidPtr) Nodes);
  538.  
  539.     return OffsetCrv;
  540. }
  541.  
  542. /******************************************************************************
  543. * Given a srf and parameter value u,v, returns the tangent direction in Dir.  *
  544. ******************************************************************************/
  545. CagdVecStruct *CagdSrfTangent(CagdSrfStruct *Srf, CagdRType u, CagdRType v,
  546.                                 CagdSrfDirType Dir)
  547. {
  548.     switch (Srf -> GType) {
  549.     case CAGD_SBEZIER_TYPE:
  550.         return BzrSrfTangent(Srf, u, v, Dir);
  551.     case CAGD_SBSPLINE_TYPE:
  552.         return BspSrfTangent(Srf, u, v, Dir);
  553.     case CAGD_SPOWER_TYPE:
  554.         FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
  555.         return NULL;
  556.     default:
  557.         FATAL_ERROR(CAGD_ERR_UNDEF_SRF);
  558.         return NULL;
  559.     }
  560. }
  561.  
  562. /******************************************************************************
  563. * Given a srf and parameter values u,v, returns the surface normal at u,v.    *
  564. ******************************************************************************/
  565. CagdVecStruct *CagdSrfNormal(CagdSrfStruct *Srf, CagdRType u, CagdRType v)
  566. {
  567.     switch (Srf -> GType) {
  568.     case CAGD_SBEZIER_TYPE:
  569.         return BzrSrfNormal(Srf, u, v);
  570.     case CAGD_SBSPLINE_TYPE:
  571.         return BspSrfNormal(Srf, u, v);
  572.     case CAGD_SPOWER_TYPE:
  573.         FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
  574.         return NULL;
  575.     default:
  576.         FATAL_ERROR(CAGD_ERR_UNDEF_SRF);
  577.         return NULL;
  578.     }
  579. }
  580.  
  581. /******************************************************************************
  582. * Given a surface and an offset amount Offset, returns an approximation to    *
  583. * the offset surface by offseting the control mesh in the normal direction.   *
  584. ******************************************************************************/
  585. CagdSrfStruct *CagdSrfOffset(CagdSrfStruct *Srf, CagdRType OffsetDist)
  586. {
  587.     CagdBType
  588.     IsNotRational = !CAGD_IS_RATIONAL_SRF(Srf);
  589.     int    i, Row, Col,
  590.     MaxCoord = CAGD_NUM_OF_PT_COORD(Srf -> PType),
  591.     UOrder = Srf -> UOrder,
  592.     VOrder = Srf -> VOrder,
  593.     ULength = Srf -> ULength,
  594.     VLength = Srf -> VLength;
  595.     CagdBType
  596.     HasNewKV = FALSE;
  597.     CagdVecStruct *N;
  598.     CagdSrfStruct
  599.     *OffsetSrf = CagdSrfCopy(Srf);
  600.     CagdRType *UNodes, *VNodes, *UNodePtr, *VNodePtr,
  601.     **Points = OffsetSrf -> Points,
  602.     *UKV = NULL,
  603.     *VKV = NULL;
  604.  
  605.     switch (Srf -> GType) {
  606.     case CAGD_SBEZIER_TYPE:
  607.         HasNewKV = TRUE;
  608.         UKV = BspKnotUniformOpen(ULength, UOrder, NULL);
  609.         VKV = BspKnotUniformOpen(VLength, VOrder, NULL);
  610.         break;
  611.     case CAGD_SBSPLINE_TYPE:
  612.         UKV = Srf -> UKnotVector;
  613.         VKV = Srf -> VKnotVector;
  614.         break;
  615.     case CAGD_SPOWER_TYPE:
  616.         FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
  617.         return NULL;
  618.     default:
  619.         FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
  620.         return NULL;
  621.     }
  622.  
  623.     UNodes = BspKnotNodes(UKV, ULength + UOrder, UOrder);
  624.     VNodes = BspKnotNodes(VKV, VLength + VOrder, VOrder);
  625.  
  626.     if (IsNotRational)
  627.     for (Row = 0, VNodePtr = VNodes; Row < VLength; Row++, VNodePtr++)
  628.         for (Col = 0, UNodePtr = UNodes; Col < ULength; Col++, UNodePtr++) {
  629.             N = CagdSrfNormal(Srf, *UNodePtr, *VNodePtr);
  630.             for (i = 1; i <= MaxCoord; i++)
  631.             Points[i][CAGD_MESH_UV(OffsetSrf, Col, Row)] +=
  632.             N -> Vec[i - 1] * OffsetDist;
  633.         }
  634.     else
  635.     for (Row = 0, VNodePtr = VNodes; Row < VLength; Row++, VNodePtr++)
  636.         for (Col = 0, UNodePtr = UNodes; Col < ULength; Col++, UNodePtr++) {
  637.             N = CagdSrfNormal(Srf, *UNodePtr, *VNodePtr);
  638.             for (i = 1; i <= MaxCoord; i++)
  639.                 Points[i][CAGD_MESH_UV(OffsetSrf, Col, Row)] +=
  640.             N -> Vec[i - 1] * OffsetDist *
  641.                 Points[W][CAGD_MESH_UV(OffsetSrf, Col, Row)];
  642.         }
  643.  
  644.     if (HasNewKV) {
  645.     CagdFree((VoidPtr) UKV);
  646.     CagdFree((VoidPtr) VKV);
  647.     }
  648.  
  649.     CagdFree((VoidPtr) UNodes);
  650.     CagdFree((VoidPtr) VNodes);
  651.  
  652.     return OffsetSrf;
  653. }
  654.  
  655. /******************************************************************************
  656. * Return a new reversed surface by reversing in U direction the control mesh. *
  657. ******************************************************************************/
  658. CagdSrfStruct *CagdSrfReverse(CagdSrfStruct *Srf)
  659. {
  660.     CagdBType
  661.     IsNotRational = !CAGD_IS_RATIONAL_SRF(Srf);
  662.     int i, Len, Row, Col,
  663.     ULength = Srf -> ULength,
  664.     VLength = Srf -> VLength,
  665.     MaxCoord = CAGD_NUM_OF_PT_COORD(Srf -> PType);
  666.     CagdSrfStruct
  667.     *ReversedSrf = CagdSrfCopy(Srf);
  668.     CagdRType *KV,
  669.     **Points = ReversedSrf -> Points;
  670.  
  671.     switch (Srf -> GType) {
  672.     case CAGD_SBEZIER_TYPE:
  673.     case CAGD_SBSPLINE_TYPE:
  674.         break;
  675.     case CAGD_SPOWER_TYPE:
  676.         FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
  677.         return NULL;
  678.     default:
  679.         FATAL_ERROR(CAGD_ERR_UNDEF_SRF);
  680.         return NULL;
  681.     }
  682.  
  683.     /* Reverse the Mesh: */
  684.     Len = ULength / 2;
  685.     for (Row = 0; Row < VLength; Row++)
  686.     for (Col = 0; Col < Len; Col++)
  687.         for (i = IsNotRational; i <= MaxCoord; i++)
  688.         SWAP(CagdRType,
  689.              Points[i][Row * ULength + Col],
  690.              Points[i][Row * ULength + ULength - Col - 1]);
  691.  
  692.     /* Reverse the U knot vector if it exists: */
  693.     if (Srf -> GType == CAGD_SBSPLINE_TYPE &&
  694.     Srf -> UKnotVector != NULL) {
  695.     KV = BspKnotReverse(Srf -> UKnotVector, Srf -> UOrder + ULength);
  696.     CagdFree((VoidPtr) ReversedSrf -> UKnotVector);
  697.     ReversedSrf -> UKnotVector = KV;
  698.     }
  699.  
  700.     return ReversedSrf;
  701. }
  702.  
  703. /******************************************************************************
  704. * Return a new reversed surface by flipping the U and V directions.           *
  705. ******************************************************************************/
  706. CagdSrfStruct *CagdSrfReverse2(CagdSrfStruct *Srf)
  707. {
  708.     CagdBType
  709.     IsNotRational = !CAGD_IS_RATIONAL_SRF(Srf);
  710.     int i, Row, Col,
  711.     ULength = Srf -> ULength,
  712.     VLength = Srf -> VLength,
  713.     MaxCoord = CAGD_NUM_OF_PT_COORD(Srf -> PType);
  714.     CagdSrfStruct
  715.     *ReversedSrf = CagdSrfCopy(Srf);
  716.     CagdRType
  717.     **Points = Srf -> Points,
  718.     **RevPoints = ReversedSrf -> Points;
  719.  
  720.     switch (Srf -> GType) {
  721.     case CAGD_SBEZIER_TYPE:
  722.     case CAGD_SBSPLINE_TYPE:
  723.         break;
  724.     case CAGD_SPOWER_TYPE:
  725.         FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
  726.         return NULL;
  727.     default:
  728.         FATAL_ERROR(CAGD_ERR_UNDEF_SRF);
  729.         return NULL;
  730.     }
  731.  
  732.     /* Reverse the Mesh: */
  733.     for (Row = 0; Row < VLength; Row++)
  734.     for (Col = 0; Col < ULength; Col++)
  735.         for (i = IsNotRational; i <= MaxCoord; i++)
  736.         RevPoints[i][Col * VLength + Row] =
  737.             Points[i][Row * ULength + Col];
  738.  
  739.     /* Swap the U and the V knot vectors if the exists: */
  740.     if (Srf -> GType == CAGD_SBSPLINE_TYPE) {
  741.     SWAP(CagdRType *,
  742.          ReversedSrf -> UKnotVector, ReversedSrf -> VKnotVector);
  743.     }
  744.  
  745.     /* And swap the orders and lengths. */
  746.     SWAP(int, ReversedSrf -> UOrder, ReversedSrf -> VOrder);
  747.     SWAP(int, ReversedSrf -> ULength, ReversedSrf -> VLength);
  748.  
  749.     return ReversedSrf;
  750. }
  751.